﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System.Text;
using XinLife.Core.Caches;

namespace XinLife.Common.Filters
{
    public class CacheableFilter : IAsyncActionFilter
    {
        private readonly ICaching _cache;

        public CacheableFilter(ICaching cache)
        {
            _cache = cache;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var Endpoint = context.HttpContext.GetEndpoint();
            var cacheableAttribute = Endpoint?.Metadata.GetMetadata<CacheableAttribute>();

            if (cacheableAttribute != null)
            {
                var cacheKey = GenerateCacheKey(context);
                if (_cache.TryGetValue<ObjectResult>(cacheKey, out var cachedResult))
                {
                    context.Result = (IActionResult)cachedResult;
                    return;
                }

                var executedContext = await next();

                if (executedContext.Result is ObjectResult objectResult)
                {
                    _cache.Set(cacheKey, objectResult, TimeSpan.FromMinutes(cacheableAttribute.DurationInSeconds));
                }
            }
            else
            {
                await next();
            }
        }

        private static string GenerateCacheKey(ActionExecutingContext context)
        {
            var stringBuilder = new StringBuilder();
            stringBuilder.Append($"{context.HttpContext.Request.Path}");

            foreach (var (key, value) in context.ActionArguments)
            {
                stringBuilder.Append($"|{key}={value}");
            }

            return stringBuilder.ToString();
        }
    }
}
